package org.codetranslators.tools.XMLUtils;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.codetranslators.common.ControlFlowGraph;
import org.codetranslators.compiler.intermrep.AssemblyInstruction;
import org.dom4j.Attribute;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class XmlReader {

	
	public Vector<ControlFlowGraph> readXml(String fileName) throws IOException,DocumentException{
		
		SAXReader reader = new SAXReader();
		File inFile = new File(fileName);
		FileReader fileReader = new FileReader(inFile);
		org.dom4j.Document document = reader.read(fileReader);
		Vector<ControlFlowGraph> cfgs = new Vector<ControlFlowGraph>();
		ControlFlowGraph cfg = null;
		Element rootElement = document.getRootElement();
		System.out.println("root element is --"+rootElement.getQualifiedName());
		
		if(rootElement.getQualifiedName().equalsIgnoreCase("cfg-set")){
			Iterator it = rootElement.elementIterator();
			ArrayList<XmlCFGInfo> cfgsInfo = new ArrayList<XmlCFGInfo>();		
			while(it.hasNext()){
				Element element = (Element)it.next();
				if(element.getQualifiedName().equalsIgnoreCase("cfg")){
					cfg = readCompleteCFGNode(element);
					cfgs.add(cfg);
				}
			}
		}
		
		return cfgs;
	}
	
	public ControlFlowGraph readCompleteCFGNode(Element element){
		
		Iterator childs = element.elementIterator();
		Vector instList = new Vector();
		while(childs.hasNext()){
			int id = 0;
			String name = null;
			boolean startNode = false;
			boolean endNode = false;
			Element childNode = (Element)childs.next();
			if("node".equals(childNode.getQualifiedName())){		
				
				Iterator instructionInfo = childNode.elementIterator();				
				
				while(instructionInfo.hasNext()){
					Element instrElement = (Element)instructionInfo.next();
					Iterator useAndDefsIter = instrElement.elementIterator();	
					Vector useIntructions = new Vector();
					Vector defInstructions = new Vector();		
					List<String> instrctionsInfo = new ArrayList<String>();
					if("instruction".equals(instrElement.getQualifiedName())){
						Iterator attributeIterator = instrElement.attributeIterator();
						String instruction = null;
						String type = null;
						String fname = null;
						while(attributeIterator.hasNext()){
							Attribute instructionAttribute = (Attribute)attributeIterator.next();
							
							
							if("ins".equals(instructionAttribute.getQualifiedName())){
								instruction = instructionAttribute.getValue();
								instrctionsInfo.add(instruction);
								//instrctionsInfo.add(XmlToAssemblyInstruction.getAssemblyInstruction(type)instructionAttribute.getValue());
							}
							else if("type".equals(instructionAttribute.getQualifiedName())){
								type  = instructionAttribute.getValue();
								//instrctionsInfo.add(XmlToAssemblyInstruction.getAssemblyInstruction(type)instructionAttribute.getValue());
							}
							else if("fname".equals(instructionAttribute.getQualifiedName())){
								fname  = instructionAttribute.getValue();
								//instrctionsInfo.add(XmlToAssemblyInstruction.getAssemblyInstruction(type)instructionAttribute.getValue());
							}
						}
						while(useAndDefsIter.hasNext()){
							Element useOrDefInstruction = (Element)useAndDefsIter.next();
							if("use".equals(useOrDefInstruction.getQualifiedName())){											
								useIntructions.add(new String(useOrDefInstruction.getTextTrim()));
							}
							if("def".equals(useOrDefInstruction.getQualifiedName())){
								defInstructions.add(new String(useOrDefInstruction.getTextTrim()));
							}
						}
						
						if(instruction !=null && type !=null){
							AssemblyInstruction assemblyInstruction = new XmlToAssemblyInstruction().getInstruction(instrElement,type, useIntructions, defInstructions);
							//XmlToAssemblyInstruction.getAssemblyInstruction(type, instruction.trim(),fname, useIntructions, defInstructions);
							instList.add(assemblyInstruction);
						}
						//instrctionsInfo.add(instrElement.getText());									
					}		
				}
			}
		}
		System.out.println(instList.size());
		ControlFlowGraph controlFlowGraph = new ControlFlowGraph(instList,false);					
		return controlFlowGraph;
	}
	
}
